package com.snts.synchronization.core;

import java.lang.reflect.Array;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SyncTable extends BaseTable {

	Synchronization synchronization;
	ExternalTable externalTable = new ExternalTable();
	List<TableReference> joinRoute = new ArrayList<TableReference>();
	TableLog tableLog = new TableLog(this);
	
	private List<Column> columns = new ArrayList<Column>();
	
	public Synchronization getSynchronization() {
		return synchronization;
	}

	public void setSynchronization(Synchronization synchronization) {
		this.synchronization = synchronization;
	}
	
	public String getPkColumnName(){
		return synchronization.getPkColumnName();
	}

	public String getCatalog() {
		return catalog;
	}

	public String getSchema() {
		return schema;
	}

	public String getName() {
		return name;
	}

	public List<Column> getColumns() {
		return columns;
	}
	
	public String getLogTableName(){
		return schema + "_" + name + "_log";
	}
	
	public BaseTable getLogTable(){
		return new BaseTable("synchronization", getLogTableName(), synchronization.isQuoteIdentifier());
	}
	
	public String getLogFunctionName(){
		return schema + "_" + name + "_logfunction";
	}
	
	public String getTriggerName(){
		return schema + "_" + name + "_logtrig";
	}
	
	public void setCatalog(String catalog) {
		this.catalog = catalog;
	}

	public void setSchema(String schema) {
		this.schema = schema;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void addColumn(Column column){
		columns.add(column);
		column.table = this;
	}
	
	public void addTableReference(TableReference tableReference){
		joinRoute.add(tableReference);
		tableReference.setSyncTable(this);
	}
	
	public JoinRoute getJoinRoute() {
		return new JoinRoute();
	}
	
	public ExternalTable getExternalTable() {
		return externalTable;
	}
	
	public void configureColumn(String name, ResultSet rs) throws SQLException {
		for(Column c : columns){
			if(name.equals(c.getName())){
				c.sqlType = rs.getInt("DATA_TYPE");
				c.typeName = rs.getString("TYPE_NAME");
				c.size = rs.getInt("COLUMN_SIZE");				
			}
		}
	}

	public Column getColumnByName(String name){
		for(Column c : columns){
			if(name.equals(c.getName())){
				return c.cloneColumn();
			}
		}
		return null;
	}
	
	public Column getColumnByExternalName(String externalName){
		for(Column c : columns){
			if(externalName.equals(c.getExternalName())){
				return c.cloneColumn();
			}
		}
		return null;
	}
	
	public boolean isUpdateAppendsLog(){
		return synchronization.isUpdateAppendsLog();
	}

	public TableLog getTableLog() {
		return tableLog;
	}
	
	@Override
	protected boolean isQuoteIdentifier() {
		return synchronization.isQuoteIdentifier();
	}

	public class JoinRoute {

		public List<TableReference> getRoute(){
			return joinRoute;
		}
		
		public TableReference getFirstTableReference(){
			return joinRoute.get(0);
		}
		
		public boolean isRestaurantId(){
			return "restaurants".equals(getFirstTableReference().getTableName());
		}
		
		public JoinTable getLastJoinTable(){
			JoinTable joinTable = null;
			if(joinRoute.size() < 2){
				joinTable = new JoinTable(SyncTable.this.getSchema(), SyncTable.this.getName(), synchronization.isQuoteIdentifier());
			} else if(joinRoute.size() > 0) {
				TableReference tableReference = joinRoute.get(joinRoute.size() - 2);
				joinTable = new JoinTable(tableReference.getSchema(), tableReference.getTableName(), synchronization.isQuoteIdentifier());
			}
			joinTable.setRestIdColumn(joinRoute.get(joinRoute.size() - 1).getForeignKey());
			return joinTable;
		}
		
		public String buildRestaurantIdQuery(){
			return null;
/*			JoinTable joinTable = getLastJoinTable();
			StringBuffer buf = new StringBuffer("select ");
			buf.append(getTableAlias(joinTable));
			buf.append(".");
			buf.append(joinTable.getRestIdColumn());
			buf.append(" from ");
			buf.append(getQualifiedName());
			buf.append(" ");
			buf.append(getTableAlias(SyncTable.this));
			List<TableReference> subList = joinRoute.subList(0, joinRoute.size() - 1);
			for(TableReference tr : subList){
				buf.append(", ");
				buf.append(tr.getQualifiedName());
				buf.append(" ");
				buf.append(getTableAlias(tr));
			}
			buf.append(" where ");
			BaseTable lastTable = SyncTable.this;
			for(int i = 0; i < subList.size(); i ++){
				TableReference tr = subList.get(i);
				buf.append(getTableAlias(tr));
				buf.append('.');
				buf.append(getPkColumnName());
				buf.append('=');
				buf.append(getTableAlias(lastTable));
				buf.append('.');
				buf.append(tr.getForeignKey());
				buf.append(" and ");
				lastTable = tr;
			}
			buf.append(getTableAlias(SyncTable.this));
			buf.append('.');
			buf.append(getPkColumnName());
			buf.append("=?");
			return buf.toString();*/
		}
		
	}

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		Class.forName("org.postgresql.Driver");
		Connection conn = DriverManager.getConnection(
				"jdbc:postgresql://127.0.0.1:5432/Restaurant", "postgres",
				"123");	
		Synchronization synchronization = new Synchronization();
		synchronization.load(conn.getMetaData());
		BaseTable syncTable = synchronization.getTables().get(0);
//		System.out.println(syncTable.getJoinRoute().buildQuery());
	}

}
